package com.smsclient.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.smsclient.constant.GlobalConstant;
import com.smsclient.exception.BusinessException;
import com.smsclient.init.CommonFacade;
import com.smsclient.mapper.MobileDataRepository;
import com.smsclient.model.IspType;
import com.smsclient.model.MobileDataViewVo;
import com.smsclient.model.SMSCheckVo;
import com.smsclient.model.SMSModel;
import com.smsclient.model.entity.SmsOrgTemplate;
import com.smsclient.model.entity.MobileData;
import com.smsclient.service.SmsOrgTemplateService;
import com.smsclient.service.SMSService;
import com.smsclient.util.SendSMSUtil;
import com.zx.sms.BaseMessage;
import com.zx.sms.codec.cmpp.msg.CmppSubmitRequestMessage;
import com.zx.sms.codec.cmpp.msg.CmppSubmitResponseMessage;
import com.zx.sms.common.util.ChannelUtil;
import com.zx.sms.connect.manager.cmpp.CMPPClientEndpointEntity;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service("smsService")
@Slf4j
public class SMSServiceImpl implements SMSService {

    @Resource(name = "CMPPClientEndpointEntity")
    private CMPPClientEndpointEntity cmppClientEndpointEntity;

    @Value(value = "${cmppconfig.smsserve.srcid}")
    private String srcid;

    @Autowired
    private CommonFacade commonFacade;

    @Autowired
    private MobileDataRepository mobileDataRepository;

    @Autowired
    private SmsOrgTemplateService smsOrgTemplateService;

    @Override
    public Object sendSMSDatas(SMSModel smsModel) throws Exception {
        List<String> mobileList = smsModel.getMobile();
        List<MobileDataViewVo> mobileDataViewVos = Lists.newArrayList();
        if(CollectionUtil.isNotEmpty(mobileList)){
            for(String mobile : mobileList){
                MobileDataViewVo viewVo = this.sendSMSData(mobile,smsModel.getContext());
                mobileDataViewVos.add(viewVo);
            }
        }
        return mobileDataViewVos;
    }

    public MobileDataViewVo sendSMSData(String mobileNum,String  text) throws Exception {
        String prefixMobile = this.checkMobileNum(mobileNum);
        String ispType = commonFacade.getIspDictType(prefixMobile);
        MobileDataViewVo viewVo = new MobileDataViewVo();
        if (StrUtil.equalsIgnoreCase(ispType, cmppClientEndpointEntity.getGroupName())) {
            //移动 对接 代理商
            CmppSubmitRequestMessage msg = new CmppSubmitRequestMessage();
            msg.setDestterminalId(mobileNum);
            msg.setSrcId(srcid);
            SmsOrgTemplate template = smsOrgTemplateService.getOrgTempalte(commonFacade.getCurrentOrgId());
            String content = SendSMSUtil.resourceSmsStr(template.getSignature(),template.getTamplateStr()) + text;
            log.info("sms_content:" + content);
            msg.setMsgContent(content);
            msg.setRegisteredDelivery((short) 1);
            log.info("CmppSubmitRequestMessage：" + msg.toString());
            //调用方法发送短信
            log.info(cmppClientEndpointEntity.getId());
            MobileData mobileData = new MobileData();
            mobileData.setIspCode(ispType);
            mobileData.setIspName(IspType.getName(ispType));
            mobileData.setMobileNum(mobileNum);
            mobileData.setSyncFlag(1);
            mobileData.setOrgId(commonFacade.getCurrentOrgId());
            mobileData.setMsg(content);
            mobileData.setStatus(GlobalConstant.STAS_INIT);
            commonFacade.freshCreateData(mobileData);
            mobileData = mobileDataRepository.save(mobileData);
            this.sendSMS(cmppClientEndpointEntity.getId(), msg,mobileData);

            while(true){
                mobileData = mobileDataRepository.findById(mobileData.getId()).get();
                if(!StringUtils.equalsIgnoreCase(GlobalConstant.STAS_INIT,mobileData.getStatus())){
                    BeanUtils.copyProperties(mobileData,viewVo);
                    break;
                }else{
                    Thread.sleep(100);
                }
            }
        }
        return viewVo;
    }

    private String checkMobileNum(String moblie) throws BusinessException {
        if (StrUtil.isNotBlank(moblie)) {
            if (moblie.length() > 11) {
                String subMoblie = moblie.substring(moblie.length() - 11);
                return checkMobileNum(subMoblie);
            } else if (moblie.length() < 11) {
                log.warn("{1} : invalid mobile number!", moblie);
                throw new BusinessException(String.format("%s : invalid mobile number!", moblie));
            } else {
                String prefixMobile = moblie.substring(0, 3);
                log.info(prefixMobile);
                return prefixMobile;
            }
        } else {
            throw new BusinessException("empty Mobile Number!");
        }
    }

    public  void sendSMS(String clientId, BaseMessage msg,MobileData mobileData) throws Exception {
        List<Promise<BaseMessage>> futures = ChannelUtil.syncWriteLongMsgToEntity(clientId, msg);
        if (futures != null) {
            try {
                for (Promise<BaseMessage> future : futures) {
                    future.addListener(new GenericFutureListener<Future<BaseMessage>>() {
                        @Override
                        public void operationComplete(Future<BaseMessage> future) throws Exception {
                            if (future.isSuccess()) {
                                log.info("response:{}", future.get());
                            } else {
                                log.error("response:{}", future.cause());
                            }
                            CmppSubmitResponseMessage responseMessage  = (CmppSubmitResponseMessage) future.get();
                            mobileData.setMsgId(responseMessage.getMsgId().toString());
                            mobileData.setStatus(String.valueOf(responseMessage.getResult()));
                            mobileDataRepository.save(mobileData);
                        }
                    });
                    try {
                        future.sync();
                    } catch (Exception ex) {
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public Object checkSmsStatus(SMSCheckVo checkVo) {
        List list = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(checkVo.getSmsIdList())) {
            list = checkVo.getSmsIdList().stream().map(p -> {
                Map map = new ConcurrentHashMap();
                String resultStr = "";
                Optional<MobileData> optionalData = mobileDataRepository.findById(p);
                if (optionalData.isPresent()) {
                    MobileData mobileData = optionalData.get();
                    if (1 == mobileData.getSyncFlag()) {
                        resultStr = "此条短信等待中.";
                    } else {
                        MobileData resultData = mobileDataRepository.findByReturnMsgId(mobileData.getReturnMsgId());
                        resultStr = StrUtil.equalsIgnoreCase(GlobalConstant.STAS_DELIVRD, resultData.getStatus()) ? "短信发送成功!" : resultData.getStatus();
                    }
                }
                map.put(p, resultStr);
                return map;
            }).collect(Collectors.toList());
        }
        return list;
    }
}
